package com.example.alibabanacosdiscoveryclient01;

import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRule;
import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRuleManager;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowItem;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRuleManager;
import com.alibaba.csp.sentinel.slots.system.SystemRule;
import com.alibaba.csp.sentinel.slots.system.SystemRuleManager;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

@EnableDiscoveryClient
@SpringBootApplication
//@EnableFeignClients
//@EnableScheduling
//@EnableSchedulerLock(defaultLockAtMostFor = "30s")
@MapperScan(value = {"com.example.alibabanacosdiscoveryclient01.mapper"})
public class AlibabaNacosDiscoveryClient01Application {

    public static void main(String[] args) {
        SpringApplication.run(AlibabaNacosDiscoveryClient01Application.class, args);
//        initFlowRules();//限流
//        intDegradeRules();//熔断
//        initSystemRule();//系统保护
//        initWhiteRules();//白名单
//        initBlackRules();//黑名单
//        initParamFlowRules();//热点参数
    }

    /*******************mcp 手动**********************************/
    /*
    @Bean
    public CommandLineRunner predefinedQuestions(ChatClient.Builder chatClientBuilder,
                                                 List<SyncMcpToolCallback> functionCallbacks, ConfigurableApplicationContext context) {

        return args -> {
            var chatClient = chatClientBuilder
                    .defaultFunctions(functionCallbacks.toArray(new SyncMcpToolCallback[0]))
                    .build();


            // Question 1
            String question1 = "你能解释一下spring-ai-mcp-overview.txt文件的内容吗？";
            System.out.println("QUESTION: " + question1);
            System.out.println("ASSISTANT: " + chatClient.prompt(question1).call().content());

            // Question 2
            String question2 = "请将spring-ai-mcp-overview.txt文件的内容进行汇总，要中文，并保存为新的summary.md为Markdown格式";
            System.out.println("\nQUESTION: " + question2);
            System.out.println("ASSISTANT: " +
                    chatClient.prompt(question2).call().content());

            context.close();

        };
    }

    @Bean
    public List<SyncMcpToolCallback> functionCallbacks(McpSyncClient mcpClient) {

        var callbacks = mcpClient.listTools(null)
                .tools()
                .stream()
                .map(tool -> new SyncMcpToolCallback(mcpClient, tool))
                .toList();
        return callbacks;
    }

    @Bean(destroyMethod = "close")
    public McpSyncClient mcpClient() {

        // based on
        // https://github.com/modelcontextprotocol/servers/tree/main/src/filesystem
        var stdioParams = ServerParameters.builder("D:\\developdependence\\node\\npx.cmd")
                .args("-y", "@modelcontextprotocol/server-filesystem", getFilePath())
                .build();

        var mcpClient = McpClient.sync(new StdioClientTransport(stdioParams))
                .requestTimeout(Duration.ofSeconds(10)).build();

        var init = mcpClient.initialize();

        System.out.println("MCP Initialized: " + init);

        return mcpClient;

    }

    private static String getFilePath() {
        String path = System.getenv("MCP_FILE_DIRECTORY_PATH");
        return StringUtils.isEmpty(path) ? getDbPath() : path;
    }

    private static String getDbPath() {
        return Paths.get(System.getProperty("user.dir")).toString();
    }
    */
    /*****************************************************/


    private static void initFlowRules() {
        List<FlowRule> flowRules = new ArrayList<FlowRule>();
        FlowRule flowRule = new FlowRule();
        flowRule.setResource("hello");
        flowRule.setCount(10);//每秒不超过10个请求
        flowRule.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_DEFAULT);
        flowRule.setStrategy(RuleConstant.STRATEGY_DIRECT);
        flowRule.setGrade(RuleConstant.FLOW_GRADE_QPS);
        flowRule.setLimitApp("default");
        flowRules.add(flowRule);
        FlowRuleManager.loadRules(flowRules);
    }
    private static void intDegradeRules() {
        List<DegradeRule> degradeRules = new ArrayList<DegradeRule>();
        DegradeRule degradeRule1 = new DegradeRule();
        degradeRule1.setResource("hello");
        degradeRule1.setCount(5);
        degradeRule1.setMinRequestAmount(1);
        degradeRule1.setTimeWindow(30);
        degradeRule1.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT);
        degradeRule1.setLimitApp("default");
        degradeRules.add(degradeRule1);

//        DegradeRule degradeRule2 = new DegradeRule();
//        degradeRule2.setResource("hello");
//        degradeRule2.setCount(1);
//        degradeRule2.setGrade(RuleConstant.DEGRADE_GRADE_RT);
//        degradeRule2.setSlowRatioThreshold(0.1);
//        degradeRule2.setMinRequestAmount(1);
//        degradeRule2.setTimeWindow(30);
//        degradeRule2.setLimitApp("default");
//        degradeRules.add(degradeRule2);

        DegradeRuleManager.loadRules(degradeRules);
    }
    private static  void initSystemRule() {
        List<SystemRule> rules = new ArrayList<>();
        SystemRule rule = new SystemRule();
        // max load is 3
        rule.setHighestSystemLoad(3.0);
        // max cpu usage is 60%
        rule.setHighestCpuUsage(0.6);
        // max avg rt of all request is 10 ms
        rule.setAvgRt(10);
        // max total qps is 20
        rule.setQps(20);
        // max parallel working thread is 10
        rule.setMaxThread(10);
        rules.add(rule);
        SystemRuleManager.loadRules(rules);
    }
    private static void initWhiteRules() {
        AuthorityRule rule = new AuthorityRule();
        rule.setResource("white");
        rule.setStrategy(RuleConstant.AUTHORITY_WHITE);
        rule.setLimitApp("client");
        AuthorityRuleManager.loadRules(Collections.singletonList(rule));
    }
    private static void initBlackRules() {
        AuthorityRule rule = new AuthorityRule();
        rule.setResource("black");
        rule.setStrategy(RuleConstant.AUTHORITY_BLACK);
        rule.setLimitApp("client");
        AuthorityRuleManager.loadRules(Collections.singletonList(rule));
    }
    private static void initParamFlowRules(){
        ParamFlowRule rule = new ParamFlowRule("hello")
                .setParamIdx(0)//参数索引位置
                .setCount(5);//qps全局阈值5
        //针对string类型的参数 name，单独设置限流 QPS 阈值为 1，而不是全局的阈值 5.
        ParamFlowItem item = new ParamFlowItem().setObject("name")
                .setClassType(String.class.getName())
                .setCount(1);//阈值1
        rule.setParamFlowItemList(Collections.singletonList(item));
        ParamFlowRuleManager.loadRules(Collections.singletonList(rule));
    }
}
